package com.todod.common.exceptionHandler;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestClientException;

import com.alibaba.fastjson.JSONObject;
import com.todod.entity.ResultData;
import com.todod.exception.BusinessException;
import com.todod.exception.LoginExpiredException;
import com.todod.exception.LoginOutException;
import com.todod.exception.SingleLoginException;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.util.SaFoxUtil;


/**
 * 统一异常处理
 *
 * @author gsh
 * @version 创建时间：2018年11月30日 下午5:25:35
 */
@ControllerAdvice
public class CommonExceptionHandler {

    Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 参数校验失败
     *
     * @param ex
     * @return
     * @Title: handleBindException
     * @Description:
     * @author gsh
     * @date 2019年8月13日
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public ResultData handleBindException(BindException ex) {
        // ex.getFieldError():随机返回一个对象属性的异常信息。如果要一次性返回所有对象属性异常信息，则调用ex.getAllErrors();
        FieldError fieldError = ex.getFieldError();

        log.warn("参数校验失败异常：-----------------" + fieldError.getDefaultMessage());
        return ResultData.error(ResultData.PARAM_ERROR_CODE, fieldError.getDefaultMessage());
    }

    /**
     * 参数校验失败
     *
     * @param ex
     * @return
     * @Title: handleBindException
     * @Description:
     * @author gsh
     * @date 2020年7月15日
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ResultData handleBindException(MethodArgumentNotValidException ex) {
        List<ObjectError> errors = ex.getBindingResult().getAllErrors();
        String message = "参数不合法";
        if (errors.size() > 0) {
            message = errors.get(0).getDefaultMessage();
        }
        log.warn("参数校验失败异常：-----------------" + message);
        return ResultData.error(ResultData.PARAM_ERROR_CODE, message);
    }

    /**
     * 请求方式不正确
     *
     * @param e
     * @return
     * @Title: exceptionHandler
     * @Description:
     * @author gsh
     * @date 2019年10月14日
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ResultData exceptionHandler(HttpRequestMethodNotSupportedException e) {
        log.warn("请求方式不正确", e.getMessage());
        return ResultData.error(ResultData.METHOD_NOT_SUPPORTED, e.getMessage());
    }

    /**
     * 拦截Exception类的异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResultData exceptionHandler(Exception e) {

        log.error("error-info", e);

        return ResultData.error("系统异常");
    }

    /**
     * restTemplate 请求异常
     *
     * @param e
     * @return
     * @Title: exceptionHandler
     * @Description:
     * @author gsh
     * @date 2019年10月15日
     */
    @ExceptionHandler(RestClientException.class)
    @ResponseBody
    public ResultData exceptionHandler(RestClientException e) {

        log.error("error-info", e);

        return ResultData.error(ResultData.REQUEST_INTERFACE_ERROE_CODE, "请求接口异常:" + e.getMessage());
    }

    /**
     * @param e
     * @return
     * @return Map<String, Object>
     * @Title: exceptionHandler
     * @Description: 自定义异常处理
     * @author：gsh
     * @date: 2018年11月30日
     */
    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResultData exceptionHandler(BusinessException e) {
        log.warn("自定义异常：-----------------" + e.getMessage());
        return ResultData.error(ResultData.ESTIMATE_ERROR_CODE, e.getMessage());
    }

    /**
     * 用户登陆过期
     *
     * @param e
     * @return
     * @Title: exceptionHandler
     * @Description:
     * @author gsh
     * @date 2019年10月11日
     */
    @ExceptionHandler(LoginExpiredException.class)
    @ResponseBody
    public ResultData exceptionHandler(LoginExpiredException e) {
        JSONObject data = new JSONObject();
        String host = SaHolder.getRequest().getUrl().replaceAll(SaHolder.getRequest().getRequestPath(), "");
        String clientLoginUrl = host + "/sso/login?back=" + SaFoxUtil.encodeUrl(SaHolder.getRequest().getHeader("client-url"));
        data.put("clientLoginUrl", clientLoginUrl);
        //SaHolder.getRequest().getHeader("client-url")
        return ResultData.error(ResultData.USER_LOGIN_EXPIRED, e.getMessage(), data);
    }

    /**
     * 用户未过期
     *
     * @param e
     * @return
     * @Title: exceptionHandler
     * @Description:
     * @author gsh
     * @date 2019年10月11日
     */
    @ExceptionHandler(LoginOutException.class)
    @ResponseBody
    public ResultData exceptionHandler(LoginOutException e) {
        return ResultData.error(ResultData.USER_NOT_LOGIN, e.getMessage());
    }

    /**
     * 单用户登录异常
     *
     * @param e
     * @return
     * @Title: exceptionHandler
     * @Description:
     * @author gsh
     * @date 2019年10月11日
     */
    @ExceptionHandler(SingleLoginException.class)
    @ResponseBody
    public ResultData exceptionHandler(SingleLoginException e) {
        return ResultData.error(ResultData.SINGLE_LOGIN_ERROR, e.getMessage());
    }
}
